package repositorios;

import entidades.Processo;
import excessoes.DAOException;
import interfaces.InterfaceProcessoDAO;
import java.util.Date;
import java.util.List;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.ReplicationMode;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.exception.ConstraintViolationException;

/**
 *
 * @author Marcelo Gomes Neto
 */
public class ProcessoDAOHibernate implements InterfaceProcessoDAO 
{
    private Session session;

    public void setSessao(Session session) {
        this.session = session;
    }

    @Override
    public Processo carregarProcesso(Integer id) throws DAOException {
        return (Processo) this.session.get(Processo.class, id);
    }

    @Override
    public void incluirProcesso(Processo processo) throws DAOException {
        try {
            this.session.save(processo);
        }
        catch (ConstraintViolationException e) {
            throw new DAOException("Erro de chave duplicada\n" + e.getConstraintName());
        }
    }
    
    @Override
    public void atualizarProcesso(Processo processo) throws DAOException
    {
        try 
        {
            Integer id = processo.getIdprocesso();
            if (id == null || id == 0)
            {
                Processo processoId = this.carregarProcesso(id);
                processoId.setIdprocesso(id);
                this.session.evict(id);
            }
            //this.session.replicate(processo, ReplicationMode.IGNORE);
            this.session.merge(processo);
        }
        catch (ConstraintViolationException e) {
            //if (e.getCause() instanceof ConstraintViolationException) {
            //FacesUtil.getFacesContext().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "O campo digitado já existe no banco de dados!", "O campo digitado já existe no banco de dados!"));
            throw new DAOException("O campo digitado já existe no banco de dados!");
            //}
        }
    }
    
    @Override
    public void manterProcesso(Processo processo) throws DAOException {
        this.session.update(processo);
    }
    
    @Override
    public void excluirProcesso(Processo processo) throws DAOException
    {
        try {
            this.session.delete(processo);
        }
        catch (ConstraintViolationException e) {
            throw new DAOException("Erro de chave duplicada\n" + e.getConstraintName());
        }
    }

    @Override
    public Processo buscarPorPag(String pag) 
    {
        Criteria criteria = session.createCriteria(Processo.class);
	criteria.add(Restrictions.eq("pag", pag));
        //this.session.clear();
        return (Processo) criteria.uniqueResult();
    }
    
    @Override
    public Processo buscarPorPam(String pam) 
    {
        Criteria criteria = session.createCriteria(Processo.class);
	criteria.add(Restrictions.eq("pam", pam));
        //this.session.clear();
        return (Processo) criteria.uniqueResult();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public List<Processo> listarProcessoPorOM(Integer status, Integer unidade) 
    {
        Criteria criteria = session.createCriteria(Processo.class);
        criteria.add(Restrictions.eq("status", status));
        criteria.add(Restrictions.eq("unidade", unidade));
        return criteria.list();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public List<Processo> listarProcessoPorStatus(int status)
    {
        Criteria criteria = session.createCriteria(Processo.class);
        criteria.add(Restrictions.eq("status", status));
        criteria.addOrder((Order.desc("idprocesso")));
        //this.session.clear();
        return criteria.list();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Processo> listarProcesso() 
    {
        Criteria criteria = this.session.createCriteria(Processo.class);
        criteria.addOrder((Order.desc("idprocesso")));
        return criteria.list();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public Object totalProcesso()
    {
        String hql="select count(*) from processo";
        Query consulta = this.session.createSQLQuery(hql);
        return consulta.uniqueResult();
    }
    
    @Override
    @SuppressWarnings("unchecked")
    public Object totalProcessoPorStatus(int status)
    {
        String hql="select count(*) from processo where status = "+status;
        Query consulta = this.session.createSQLQuery(hql);
        return consulta.uniqueResult();
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Processo> listarProcessoPorPeriodo(Date dataIni, Date dataFim, int status)
    {
        Criteria criteria = this.session.createCriteria(Processo.class);
        criteria.add(Restrictions.between("dataProcesso", dataIni, dataFim));  
        criteria.add(Restrictions.eq("status", status));
        criteria.addOrder((Order.desc("idprocesso")));
        return criteria.list();
    }
    
    //Retorna o maior ou último ID 
    @Override
    public Integer retornaUltimoID()
    {
        Criteria criteria = session.createCriteria(Processo.class);
        Integer maxId = (Integer) criteria.setProjection(Projections.max("id")).uniqueResult();
        
        // Condição criada para evitar retornar null ao criar o primeiro processo/tramitação
        if (maxId == null) {
            return 0;
        }
        else {
            return maxId;
        }
    }
    
    @Override
    public Processo carregarProcessoPorPag(String pag) throws DAOException 
    {
        Criteria criteria = session.createCriteria(Processo.class);
	criteria.add(Restrictions.eq("pag", pag));
        //this.session.clear();
        return (Processo) criteria.uniqueResult();
    }
    
    @Override
    public Processo carregarProcessoPorPam(String pam) throws DAOException 
    {
        Criteria criteria = session.createCriteria(Processo.class);
	criteria.add(Restrictions.eq("pam", pam));
        //this.session.clear();
        return (Processo) criteria.uniqueResult();
    }
}
